%%%-------------------------------------------------------------------
%%% @author Rain
%%% @doc 帧同步房间
%%% @end
%%%-------------------------------------------------------------------
-module(ls_room_svr).
-feature(maybe_expr,enable).

-behaviour(gen_server).
-include("elock_step.hrl").
-include("ls_room_svr.hrl").

-export([start_link/1]).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2,
    code_change/3]).

%%%===================================================================
%%% Spawning and gen_server implementation
%%%===================================================================

start_link(RoomParams) ->
    gen_server:start_link(?MODULE, [RoomParams], []).


init([RoomParams]) ->
    #{role_ids := RoleIds} = RoomParams,
    RandomSeed = floor(rand:uniform() * 100000),
    RoomRoles = [#ls_room_role{role_id = RoleId}||RoleId <- RoleIds],
    {ok, #ls_room_state{room_roles = RoomRoles, random_seed = RandomSeed}}.

%% @doc handle_call回调函数
handle_call(Req, From, State) ->
    try
        do_call(Req, From, State)
    catch
        Class:Error:StackTrace ->
            ?LS_ERROR("handle call error Req: ~p", [Req]),
            ?LS_ERROR("Class: ~p, Error: ~p, stacktrace: ~p", [Class, Error, StackTrace]),
            {reply, {'EXIT', {Error, StackTrace}}, State}
    end.

%% @doc handle_cast回调函数
handle_cast(Req, State) ->
    try
        do_cast(Req, State)
    catch
        Class:Error:StackTrace ->
            ?LS_ERROR("handle cast error Req: ~p", [Req]),
            ?LS_ERROR("Class: ~p, Error: ~p, stacktrace: ~p", [Class, Error, StackTrace]),            {noreply, State}
    end.

%% @doc handle_info回调函数
handle_info(Req, State) ->
    try
        do_info(Req, State)
    catch
        Class:Error:StackTrace ->
            ?LS_ERROR("handle info error Req: ~p", [Req]),
            ?LS_ERROR("Class: ~p, Error: ~p, stacktrace: ~p", [Class, Error, StackTrace]),
            {noreply, State}
    end.

terminate(_Reason, _State = #ls_room_state{}) ->
    ok.

code_change(_OldVsn, State = #ls_room_state{}, _Extra) ->
    {ok, State}.

%%%===================================================================
%%% Internal functions
%%%===================================================================

do_call(Req, _From, State) ->
    ?LS_WARN("unknown req: ~w", [Req]),
    {noreply, State}.

do_cast(Req, State) ->
    ?LS_WARN("unknown req: ~w", [Req]),
    {noreply, State}.

do_info({room_start, StartTime, UnitInfos}, State = #ls_room_state{}) ->
    State1 = ls_room_svr_util:do_room_start(State, StartTime, UnitInfos),
    {noreply, State1};

do_info(ls_update, State = #ls_room_state{}) ->
    State1 = ls_room_svr_util:do_ls_update(State),
    {noreply, State1};

do_info({c_change_scene_finish, RoleId}, State = #ls_room_state{}) ->
    State1 = ls_room_svr_util:do_c_change_scene_finish(RoleId, State),
    {noreply, State1};

do_info({c_reconnect, RoleId}, State = #ls_room_state{}) ->
    State1 = ls_room_svr_util:do_c_reconnect(RoleId, State),
    {noreply, State1};

do_info({c_check_hash, RoleId, Frame, Hash}, State = #ls_room_state{}) ->
    State1 = ls_room_svr_util:do_c_check_hash(RoleId, Frame, Hash, State),
    {noreply, State1};

do_info({c_frame_message, RoleId, CliFrame, LSInput}, State = #ls_room_state{}) ->
    State1 = ls_room_svr_util:do_c_frame_message(RoleId, CliFrame, LSInput, State),
    {noreply, State1};

do_info(Req, State) ->
    ?LS_WARN("unknown req: ~w", [Req]),
    {noreply, State}.
